using Circus.CodeEditor;
using Circus.CodeEditor.Serialization;
using Circus.CodeEditor.TextSource;
using Circus.Syntax;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
namespace Circus.CodeEditor
{
	public class DisplayStrings :  IStringList
	{
		internal class DisplayEnumerator : IEnumerator<string>, IDisposable, IEnumerator
		{
			private int currentIndex = -1;
			private DisplayStrings owner;
			[Description("Gets an object that represents current string.")]
			public string Current
			{
				get
				{
					string result;
					if (this.currentIndex >= 0 && this.currentIndex < this.owner.DisplayCount)
					{
						result = this.owner[this.currentIndex];
					}
					else
					{
						result = null;
					}
					return result;
				}
			}
			object IEnumerator.Current
			{
				get
				{
					return this.Current;
				}
			}
			public DisplayEnumerator(DisplayStrings owner)
			{
				this.owner = owner;
			}
			public bool MoveNext()
			{
				this.currentIndex++;
				return this.currentIndex < this.owner.DisplayCount;
			}
			public void Reset()
			{
				this.currentIndex = -1;
			}
			public virtual void Dispose()
			{
			}
		}
		private class WrapComparer : IComparer<Point>
		{
			public int Compare(Point x, Point y)
			{
				int num = x.Y - y.Y;
				if (num == 0)
				{
					num = x.X - y.X;
				}
				return num;
			}
		}
		private class LineWrapComparer : IComparer<Point>
		{
			public int Compare(Point x, Point y)
			{
				return x.Y - y.Y;
			}
		}
		private class RealWrapComparer : IComparer<Point>
		{
			public int Compare(Point x, Point y)
			{
				int num = x.Y - y.Y;
				if (num == 0)
				{
					num = Math.Max(x.X - y.X, 0);
				}
				else
				{
					num = Math.Max(num, 0);
				}
				return num;
			}
		}
		private class DisplayWrapComparer : IComparer<Point>
		{
			private DisplayStrings.WrapList list;
			public DisplayWrapComparer(DisplayStrings.WrapList list)
			{
				this.list = list;
			}
			public int Compare(Point x, Point y)
			{
				return Math.Max(x.Y + this.list.CompareIndex + 1 - y.Y, 0);
			}
		}
		internal class WrapList : SortList<Point>
		{
			private IComparer<Point> wrapComparer;
			private IComparer<Point> lineWrapComparer;
			private IComparer<Point> realWrapComparer;
			private IComparer<Point> displayWrapComparer;
			private DisplayStrings owner;
			private void GetPosAndLen(int index, int idx, ref int p, ref int len)
			{
				if (idx >= 0)
				{
					Point point = base[idx];
					if (point.Y == index - idx - 1)
					{
						p = point.X;
					}
				}
				if (idx + 1 < base.Count)
				{
					Point point = base[idx + 1];
					if (point.Y == index - idx - 1)
					{
						len = point.X - p;
					}
				}
			}
			public WrapList(DisplayStrings owner)
			{
				this.owner = owner;
				this.wrapComparer = new DisplayStrings.WrapComparer();
				this.lineWrapComparer = new DisplayStrings.LineWrapComparer();
				this.realWrapComparer = new DisplayStrings.RealWrapComparer();
				this.displayWrapComparer = new DisplayStrings.DisplayWrapComparer(this);
			}
			public void GetWrapBounds(int index, ref int p, ref int len)
			{
				if (base.Count > 0)
				{
					int idx;
					if (!base.FindLast(new Point(0, index), out idx, this.displayWrapComparer))
					{
						idx = -1;
					}
					this.GetPosAndLen(index, idx, ref p, ref len);
				}
			}
			public void GetRealPoint(ref Point point, bool checkEnd, ref bool lineEnd)
			{
				this.owner.EnsureWrapped(point.Y, true);
				int y = point.Y;
				int num;
				if (base.FindLast(new Point(0, point.Y), out num, this.displayWrapComparer))
				{
					Point point2 = base[num];
					point.Y -= num + 1;
					if (point2.Y == point.Y && point.X != int.MaxValue)
					{
						point.X += point2.X;
					}
				}
				else
				{
					num = -1;
				}
				lineEnd = false;
				int num2 = 0;
				int num3 = int.MaxValue;
				this.GetPosAndLen(y, num, ref num2, ref num3);
				if (num3 != int.MaxValue)
				{
					lineEnd = (point.X >= num2 + num3);
					if (checkEnd && lineEnd)
					{
						point.X = num2 + num3;
					}
				}
			}
			public void GetDisplayPoint(ref Point point, bool lineEnd)
			{
				this.owner.EnsureWrapped(point.Y, false);
				int num;
				if (base.FindLast(point, out num, this.realWrapComparer))
				{
					Point point2 = base[num];
					if (lineEnd && point2.X == point.X && point2.Y == point.Y)
					{
						if (num > 0)
						{
							point2 = base[num - 1];
							if (point2.Y == point.Y)
							{
								point.X -= point2.X;
							}
						}
						point.Y += num;
					}
					else
					{
						if (point2.Y == point.Y && point.X != int.MaxValue)
						{
							point.X -= point2.X;
						}
						point.Y += num + 1;
					}
				}
			}
			public int LineToDisplayLine(int index)
			{
				Point obj = new Point(int.MaxValue, index);
				int num;
				int result;
				if (base.FindLast(obj, out num, this.realWrapComparer))
				{
					result = index + num + 1;
				}
				else
				{
					result = index;
				}
				return result;
			}
			public Point AddItem(int line, int ch)
			{
				Point point = new Point(ch, line);
				int index;
				if (base.FindExact(point, out index, this.wrapComparer))
				{
					base[index] = point;
				}
				else
				{
					base.Insert(index, point);
				}
				return point;
			}
			public void ClearLines(int first, int last)
			{
				int val;
				base.FindLast(new Point(0, last), out val, this.lineWrapComparer);
				for (int i = Math.Min(val, base.Count - 1); i >= 0; i--)
				{
					int y = base[i].Y;
					if (y >= first && y <= last)
					{
						base.RemoveAt(i);
					}
					else
					{
						if (y < first)
						{
							break;
						}
					}
				}
			}
		}
		private TextStrings lines;
		private CodeEditor owner;
		private int maxLineWidth;
		private int maxLineIndex = -1;
		private bool recalcFlag = true;
		private bool lineEnd;
		private bool suppressTabs;
		private bool wordWrap;
		private bool wrapAtMargin;
		private int lastWrapped = -1;
		private int lastDisplayIndex = -1;
		private int lastWrapIndex = -1;
		private int wrapMargin;
		private bool allowOutlining;
		private OutlineOptions outlineOptions = EditConsts.DefaultOutlineOptions;
		private Outlining.OutlineList outlineList;
		private DisplayStrings.WrapList wrapList;
		private IList<Range> collapsedList;
		private int updateCount;
	    public event OutlineEvent Expanding;
	    public event OutlineEvent Collapsing;
		public virtual string this[int index]
		{
			get
			{
				string empty = string.Empty;
				StringItemInfo[] array = null;
				this.GetStringAndColorData(index, ref empty, ref array, false);
				return empty;
			}
			set
			{
			}
		}
		[Description("Gets a value indicating whether the collection is read-only.")]
		public virtual bool IsReadOnly
		{
			get
			{
				return true;
			}
		}
		public virtual int DisplayCount
		{
			get
			{
				return this.lines.Count + this.wrapList.Count - this.outlineList.CollapsedCount;
			}
		}
		public virtual bool LineEnd
		{
			get
			{
				return this.lineEnd;
			}
			set
			{
				if (this.lineEnd != value)
				{
					this.lineEnd = value;
					this.OnLineEndChanged();
				}
			}
		}
		public virtual bool Loaded
		{
			get
			{
				return !this.WordWrap || this.lastWrapped >= this.lines.Count - this.outlineList.CollapsedCount - 1;
			}
			set
			{
				this.ScanToEnd(true);
			}
		}
		public virtual bool SuppressTabs
		{
			get
			{
				return this.suppressTabs;
			}
			set
			{
				this.suppressTabs = value;
			}
		}
		[Description("Gets or sets the collection of underlying \"real\" collection of text lines.")]
		public virtual TextStrings Lines
		{
			get
			{
				return this.lines;
			}
			set
			{
				if (this.lines != value)
				{
					this.lines = value;
					this.LinesChanged();
				}
			}
		}
		[Description("Gets width of the largest line in the \"DisplayString\" object.")]
		public virtual int MaxLineWidth
		{
			get
			{
				if (this.recalcFlag && !this.owner.Scrolling.FixedScrollSize)
				{
					this.Recalculate();
				}
				return this.maxLineWidth;
			}
		}
		public virtual int Count
		{
			get
			{
				return this.DisplayCount;
			}
		}
		public string Text
		{
			get
			{
				StringBuilder stringBuilder = new StringBuilder();
				string lineTerminator = this.lines.LineTerminator;
				for (int i = 0; i < this.DisplayCount; i++)
				{
					stringBuilder.Append(this[i] + lineTerminator);
				}
				if (stringBuilder.Length >= 2)
				{
					stringBuilder.Remove(stringBuilder.Length - lineTerminator.Length, lineTerminator.Length);
				}
				return stringBuilder.ToString();
			}
			set
			{
			}
		}
	
		[Description("Gets or sets a value indicating whether a \"DisplayStrings\" object automatically wraps words to the beginning of the next line when necessary.")]
		public virtual bool WordWrap
		{
			get
			{
				return this.wordWrap;
			}
			set
			{
				if (this.wordWrap != value)
				{
					this.wordWrap = value;
					this.UpdateWordWrap();
				}
			}
		}
		[Description("Gets or sets a value indicating whether a \"DisplayStrings\" object automatically wraps words at margin position.")]
		public virtual bool WrapAtMargin
		{
			get
			{
				return this.wrapAtMargin;
			}
			set
			{
				if (this.wrapAtMargin != value)
				{
					this.wrapAtMargin = value;
					if (this.wordWrap)
					{
						this.UpdateWordWrap();
					}
				}
			}
		}
		[Description("Gets position of the wrap margin.")]
		public virtual int WrapMargin
		{
			get
			{
				int result;
				if (this.wrapAtMargin)
				{
					result = this.owner.EditMargin.Position * this.owner.Painter.FontWidth;
				}
				else
				{
					result = this.owner.ClientRect.Width - this.owner.Gutter.DisplayWidth;
				}
				return result;
			}
		}
		[Description("Gets or sets an array of chars used to separate words in a text.")]
		public virtual char[] Delimiters
		{
			get
			{
				return this.lines.Delimiters;
			}
			set
			{
				if (this.lines.Delimiters != value)
				{
					this.lines.Delimiters = value;
					this.OnDelimitersChanged();
				}
			}
		}
	
		public virtual int CollapsedCount
		{
			get
			{
				return this.allowOutlining ? this.outlineList.CollapsedList.Count : 0;
			}
		}
		[Description("Keeps track of calls to \"BeginUndoUpdate\" and \"EndUndoUpdate\" so that they can be nested.")]
		public virtual int UpdateCount
		{
			get
			{
				return this.updateCount;
			}
		}
		[Description("Gets or sets a value indicating whether outlining is enabled.")]
		public virtual bool AllowOutlining
		{
			get
			{
				return this.allowOutlining;
			}
			set
			{
				if (this.allowOutlining != value)
				{
					this.allowOutlining = value;
					this.OnAllowOutliningChanged();
				}
				if (this.owner != null)
				{
					this.owner.Invalidate();
				}
			}
		}
		[Description("Gets or sets options representing outlining appearance and behaviour.")]
		public virtual OutlineOptions OutlineOptions
		{
			get
			{
				return this.outlineOptions;
			}
			set
			{
				if (this.outlineOptions != value)
				{
					this.BeginUpdate();
					try
					{
						this.outlineOptions = value;
						this.OnOutlineOptionsChanged();
					}
					finally
					{
						this.EndUpdate();
					}
				}
			}
		}
		[Description("Gets or sets a string value that terminates line.")]
		public virtual string LineTerminator
		{
			get
			{
				return this.lines.LineTerminator;
			}
			set
			{
				this.lines.LineTerminator = value;
			}
		}
		public DisplayStrings(CodeEditor owner, TextStrings strings)
		{
			this.owner = owner;
			this.outlineList = new Outlining.OutlineList(this);
			this.wrapList = new DisplayStrings.WrapList(this);
			this.collapsedList = new List<Range>();
			this.Lines = strings;
		}
		public virtual int IndexOf(string item)
		{
			int result;
			for (int i = 0; i < this.DisplayCount; i++)
			{
				if (this[i] == item)
				{
					result = i;
					return result;
				}
			}
			result = -1;
			return result;
		}
		public virtual void Insert(int index, string item)
		{
		}
		public virtual void RemoveAt(int index)
		{
		}
		public virtual void Add(string item)
		{
		}
		public virtual void Clear()
		{
			this.lines.Clear();
			this.outlineList.Clear();
			this.collapsedList.Clear();
		}
		public virtual bool Contains(string item)
		{
			return this.IndexOf(item) >= 0;
		}
		public virtual void CopyTo(string[] array, int arrayIndex)
		{
			for (int i = arrayIndex; i < Math.Min(this.DisplayCount + arrayIndex, array.Length); i++)
			{
				array[i] = this[i - arrayIndex];
			}
		}
		public virtual bool Remove(string item)
		{
			return false;
		}
		public virtual IEnumerator<string> GetEnumerator()
		{
			return new DisplayStrings.DisplayEnumerator(this);
		}
		IEnumerator IEnumerable.GetEnumerator()
		{
			return new DisplayStrings.DisplayEnumerator(this);
		}
		private int GetLineWidth(int index)
		{
			int result;
			if (index < 0)
			{
				result = 0;
			}
			else
			{
				string empty = string.Empty;
				StringItemInfo[] colorData = null;
				this.GetStringAndColorData(index, ref empty, ref colorData, true);
				result = this.owner.SyntaxPaint.MeasureLine(empty, colorData, 0, -1);
			}
			return result;
		}
		private void GetOutlineString(int index, ref string text, ref StringItemInfo[] data, bool needData, bool applyTabs)
		{
			if (this.allowOutlining)
			{
				this.outlineList.CheckVisible(ref index);
				if (this.GetString(index, ref text, ref data, needData, false))
				{
					int length = text.Length;
					this.outlineList.GetCollapsedRanges(index, this.collapsedList);
					for (int i = this.collapsedList.Count - 1; i >= 0; i--)
					{
						OutlineRange outlineRange = this.collapsedList[i] as OutlineRange;
						if (!outlineRange.IsEmpty)
						{
							string displayText = outlineRange.DisplayText;
							int num = Math.Min(text.Length, length);
							int num2 = Math.Min(outlineRange.StartPoint.X, num);
							if (outlineRange.EndPoint.Y == index)
							{
								int num3 = Math.Min(num - num2, outlineRange.EndPoint.X - outlineRange.StartPoint.X);
								text = text.Remove(num2, num3).Insert(num2, displayText);
								if (needData)
								{
									StringItemInfo[] array = new StringItemInfo[data.Length - num3 + displayText.Length];
									Array.Copy(data, 0, array, 0, num2);
									Array.Copy(data, num2 + num3, array, num2 + displayText.Length, data.Length - num3 - num2);
									data = array;
									StringItem.SetTextStyle(ref data, num2, displayText.Length, TextStyle.OutlineSection);
								}
							}
							else
							{
								string empty = string.Empty;
								StringItemInfo[] array2 = null;
								if (this.GetString(outlineRange.EndPoint.Y, ref empty, ref array2, needData, false))
								{
									if (outlineRange.EndPoint.X < empty.Length)
									{
										text = text.Substring(0, Math.Min(num2, text.Length)) + displayText + empty.Substring(outlineRange.EndPoint.X);
									}
									else
									{
										text = text.Substring(0, Math.Min(num2, text.Length)) + displayText;
									}
									if (needData)
									{
										int num4 = Math.Max(array2.Length - outlineRange.EndPoint.X, 0);
										StringItemInfo[] array = new StringItemInfo[num2 + displayText.Length + num4];
										Array.Copy(data, 0, array, 0, num2);
										if (num4 > 0)
										{
											Array.Copy(array2, outlineRange.EndPoint.X, array, num2 + displayText.Length, num4);
										}
										data = array;
										StringItem.SetTextStyle(ref data, num2, displayText.Length, TextStyle.OutlineSection);
									}
								}
							}
						}
					}
				}
				if (applyTabs)
				{
					this.lines.GetTabString(ref text, ref data, needData && data != null, null);
				}
			}
			else
			{
				this.GetString(index, ref text, ref data, needData, applyTabs);
			}
		}
		private void GetSubString(int p, int len, ref string text, ref StringItemInfo[] data, bool needData)
		{
			int length = text.Length;
			p = Math.Min(p, length);
			len = Math.Min(len, length - p);
			text = text.Substring(p, len);
			if (needData)
			{
				StringItemInfo[] array = new StringItemInfo[len];
				Array.Copy(data, p, array, 0, len);
				data = array;
			}
		}
		private void GetWrapBounds(int index, ref int p, ref int len)
		{
			if (this.wordWrap)
			{
				this.wrapList.GetWrapBounds(index, ref p, ref len);
			}
		}
		private void Recalculate(UpdateReason reason, int x, int y, int deltaX, int deltaY)
		{
			if (!this.recalcFlag && !this.owner.Scrolling.FixedScrollSize)
			{
				int y2 = this.PointToDisplayPoint(x, y).Y;
				switch (reason)
				{
				case UpdateReason.Insert:
				{
					int lineWidth = this.GetLineWidth(y2);
					if (this.maxLineWidth < lineWidth)
					{
						this.maxLineWidth = lineWidth;
						this.maxLineIndex = y2;
					}
					break;
				}
				case UpdateReason.Delete:
					if (y2 == this.maxLineIndex)
					{
						this.recalcFlag = true;
					}
					break;
				case UpdateReason.Break:
					if (y2 == this.maxLineIndex)
					{
						this.recalcFlag = true;
					}
					else
					{
						if (y2 < this.maxLineIndex)
						{
							this.maxLineIndex++;
						}
					}
					break;
				case UpdateReason.UnBreak:
				{
					int lineWidth = this.GetLineWidth(y2);
					if (this.maxLineWidth < lineWidth)
					{
						this.maxLineWidth = lineWidth;
						this.maxLineIndex = y2;
					}
					else
					{
						if (y2 < this.maxLineIndex)
						{
							this.maxLineIndex--;
							if (this.maxLineIndex < 0)
							{
								this.recalcFlag = true;
							}
						}
					}
					break;
				}
				case UpdateReason.DeleteBlock:
				{
					int y3 = this.PointToDisplayPoint(x - deltaX, y - deltaY).Y;
					if (this.maxLineIndex >= y2 && this.maxLineIndex <= y3)
					{
						this.recalcFlag = true;
					}
					break;
				}
				case UpdateReason.InsertBlock:
				{
					int y3 = this.PointToDisplayPoint(x + deltaX, y + deltaY).Y;
					for (int i = y2; i <= y3; i++)
					{
						int lineWidth = this.GetLineWidth(i);
						if (this.maxLineWidth < lineWidth)
						{
							this.maxLineWidth = lineWidth;
							this.maxLineIndex = y2;
						}
					}
					break;
				}
				default:
					this.recalcFlag = true;
					break;
				}
			}
		}
		private void Recalculate()
		{
			this.maxLineWidth = 0;
			this.ScanToEnd(false);
			for (int i = 0; i < this.DisplayCount; i++)
			{
				int lineWidth = this.GetLineWidth(i);
				if (this.maxLineWidth < lineWidth)
				{
					this.maxLineWidth = lineWidth;
					this.maxLineIndex = i;
				}
			}
			this.recalcFlag = false;
		}
		protected void ApplyWhiteSpace(string str, ref StringItemInfo[] colorData)
		{
			for (int i = 0; i < str.Length; i++)
			{
				if (str[i] == ' ' || str[i] == '\u3000')
				{
					StringItem.SetTextStyle(ref colorData, i, 1, TextStyle.WhiteSpace);
				}
			}
		}
		protected void LinesChanged()
		{
			this.UpdateWordWrap();
			this.Recalculate();
		}
		protected int GetStringAndColorData(int index, ref string text, ref StringItemInfo[] data, bool needData)
		{
			int result = index;
			if ((this.wordWrap && this.wrapList.Count > 0) || this.allowOutlining)
			{
				Point point = new Point(0, index);
				if (this.wordWrap)
				{
					bool flag = false;
					this.wrapList.GetRealPoint(ref point, false, ref flag);
				}
				if (this.allowOutlining)
				{
					this.outlineList.GetRealPoint(ref point, false);
				}
				this.GetOutlineString(point.Y, ref text, ref data, needData, !this.suppressTabs);
				result = point.Y;
				if (this.wordWrap)
				{
					int num = 0;
					int num2 = int.MaxValue;
					this.GetWrapBounds(index, ref num, ref num2);
					if (num != 0 || num2 != int.MaxValue)
					{
						this.GetSubString(num, num2, ref text, ref data, needData && data != null);
					}
				}
			}
			else
			{
				this.GetString(index, ref text, ref data, needData, true);
			}
			return result;
		}
		protected bool GetString(int index, ref string text, ref StringItemInfo[] colorData, bool needData, bool applyTabs)
		{
			bool result;
			if (index >= 0 && index < this.lines.Count)
			{
				StringItem item = this.lines.GetItem(index);
				text = item.String;
				if (needData)
				{
					colorData = item.TextData;
					this.ApplyWhiteSpace(text, ref colorData);
				}
				if (applyTabs)
				{
					this.lines.GetTabString(ref text, ref colorData, needData, null);
				}
				result = true;
			}
			else
			{
				result = false;
			}
			return result;
		}
		protected Point DisplayPointToPoint(int x, int y, bool wrapEnd, bool rangeStart, bool tabEnd, ref bool lineEnd)
		{
			Point point = new Point(x, y);
			int num = point.Y - Math.Max(this.DisplayCount - 1, 0);
			Point result;
			if (num > 0)
			{
				if ((this.owner.NavigateOptions & NavigateOptions.BeyondEof) != NavigateOptions.None)
				{
					result = new Point(x, Math.Max(this.owner.Lines.Count - 1, 0) + num);
					return result;
				}
				point.Y -= num;
			}
			lineEnd = false;
			if (this.wordWrap)
			{
				this.wrapList.GetRealPoint(ref point, wrapEnd, ref lineEnd);
			}
			if (point.X != int.MaxValue)
			{
				string empty = string.Empty;
				StringItemInfo[] array = null;
				this.GetOutlineString(this.allowOutlining ? this.outlineList.DisplayLineToLine(point.Y) : point.Y, ref empty, ref array, false, false);
				if (!this.suppressTabs)
				{
					point.X = this.lines.PosToTabPos(empty, point.X, tabEnd);
				}
			}
			if (this.allowOutlining)
			{
				this.outlineList.GetRealPoint(ref point, rangeStart);
			}
			result = point;
			return result;
		}
		protected virtual void ScanToEnd(bool parseToEnd)
		{
			if (this.wordWrap)
			{
				this.EnsureWrapped(this.lines.Count - 1, false);
			}
			if (parseToEnd)
			{
				this.owner.Source.ParseToString(this.owner.Lines.Count - 1);
			}
		}
		protected virtual void OnLineEndChanged()
		{
		}
		public bool IsPointVisible(Point position)
		{
			bool result = true;
			Point point = this.owner.TextToScreen(position);
			if (this.owner.Scrolling.ScrollByPixels)
			{
				Rectangle clientRect = this.owner.ClientRect;
				
				{
					clientRect.X += this.owner.Gutter.Rect.Width;
					clientRect.Width -= this.owner.Gutter.Rect.Width;
				}
				if (point.X < clientRect.Left)
				{
					result = false;
				}
				else
				{
					int width = this.owner.GetCaretSize(position).Width;
					if (point.X > clientRect.Right - width)
					{
						result = false;
					}
				}
				if (point.Y < clientRect.Top)
				{
					result = false;
				}
				else
				{
					if (point.Y > clientRect.Bottom - this.owner.Painter.lineHeight)
					{
						result = false;
					}
				}
			}
			else
			{
				position = this.PointToDisplayPoint(position);
				int num = position.X - this.owner.Scrolling.WindowOriginX;
				int num2 = position.Y - this.owner.Scrolling.WindowOriginY;
				if (num < 0)
				{
					result = ((this.owner.Scrolling.Options & ScrollingOptions.UseScrollDelta) != ScrollingOptions.None);
				}
				else
				{
					int width = this.owner.GetCaretSize(this.owner.Position).Width;
					int num3 = this.owner.ClientRect.Right;
					if (point.X > num3 - width)
					{
						if ((this.owner.Scrolling.Options & ScrollingOptions.UseScrollDelta) != ScrollingOptions.None)
						{
							num3 -= num3 / EditConsts.DefaultScrollDeltaRatio;
						}
						result = false;
					}
				}
				if (num2 < 0)
				{
					result = false;
				}
				else
				{
					if (num2 > this.owner.LinesInHeight - 1)
					{
						result = false;
					}
				}
			}
			return result;
		}
		public virtual bool IsPointCollapsed(Point position, out Range range)
		{
			range = null;
            List<Range> list = new List<Range>();
			this.GetOutlineRanges(list, position);
			bool result;
			using (IEnumerator<Range> enumerator = list.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					OutlineRange outlineRange = (OutlineRange)enumerator.Current;
					if (!outlineRange.Visible)
					{
						range = outlineRange;
						result = true;
						return result;
					}
				}
			}
			result = false;
			return result;
		}
		public virtual void BlockDeleting(Rectangle rect)
		{
			if (this.allowOutlining)
			{
				this.outlineList.BlockDeleting(rect);
			}
		}
		public virtual void UpdateNeeded()
		{
			this.recalcFlag = true;
		}
		public virtual void PositionChanged(UpdateReason reason, int x, int y, int deltaX, int deltaY)
		{
			if (this.allowOutlining)
			{
				this.outlineList.PositionChanged(x, y, deltaX, deltaY);
			}
			this.Recalculate(reason, x, y, deltaX, deltaY);
		}
		public virtual Point PointToDisplayPoint(int x, int y)
		{
			return this.PointToDisplayPoint(x, y, this.lineEnd);
		}
		public virtual Point PointToDisplayPoint(Point position)
		{
			return this.PointToDisplayPoint(position.X, position.Y, this.lineEnd);
		}
		public virtual Point PointToDisplayPoint(int x, int y, bool lineEnd)
		{
			Point result = new Point(x, y);
			if (this.allowOutlining)
			{
				this.outlineList.GetDisplayPoint(ref result);
			}
			if (result.X != int.MaxValue)
			{
				string empty = string.Empty;
				StringItemInfo[] array = null;
				this.GetOutlineString(y, ref empty, ref array, false, false);
				if (!this.suppressTabs)
				{
					result.X = this.lines.TabPosToPos(empty, result.X);
				}
			}
			if (this.wordWrap)
			{
				this.wrapList.GetDisplayPoint(ref result, lineEnd);
			}
			return result;
		}
		public virtual Point DisplayPointToPoint(int x, int y)
		{
			bool flag = false;
			return this.DisplayPointToPoint(x, y, false, false, false, ref flag);
		}
		public virtual Point DisplayPointToPoint(Point position)
		{
			return this.DisplayPointToPoint(position.X, position.Y, false, false, false);
		}
		public virtual Point DisplayPointToPoint(int x, int y, ref bool lineEnd)
		{
			return this.DisplayPointToPoint(x, y, true, false, false, ref lineEnd);
		}
		public virtual Point DisplayPointToPoint(int x, int y, bool wrapEnd, bool rangeStart, bool tabEnd)
		{
			bool flag = false;
			return this.DisplayPointToPoint(x, y, wrapEnd, rangeStart, tabEnd, ref flag);
		}
		public virtual StringItemInfo[] GetColorData(int index)
		{
			string empty = string.Empty;
			StringItemInfo[] result = null;
			this.GetStringAndColorData(index, ref empty, ref result, true);
			return result;
		}
		public virtual StringItemInfo GetLexStyle(Point position)
		{
			StringItemInfo[] colorData = this.GetColorData(position.Y);
			StringItemInfo stringItemInfo = default(StringItemInfo);
			stringItemInfo.Data = 255;
			return (colorData != null && position.X >= 0 && position.X < colorData.Length) ? colorData[position.X - 1] : stringItemInfo;
		}
		public virtual int GetStringAndColorData(int index, ref string text, ref StringItemInfo[] data)
		{
			return this.GetStringAndColorData(index, ref text, ref data, true);
		}
	
		private void ClearLastLine()
		{
			this.lastWrapped = -1;
			this.lastWrapIndex = -1;
			this.lastDisplayIndex = -1;
		}
		private void EnsureWrapped(int index, bool wrapped)
		{
			if ((wrapped && index > this.lastWrapIndex) || (!wrapped && index > this.lastDisplayIndex))
			{
				if (index != int.MaxValue)
				{
					index += EditConsts.DefaultWrapDelta;
				}
				int displayLine = (this.lastWrapped + 1 > 0) ? (this.PointToDisplayPoint(int.MaxValue, this.lastWrapped).Y + 1) : 0;
				this.WrapLines(this.lastWrapped + 1, index, displayLine);
			}
		}
		private void WrapLines(int first, int last, int displayLine)
		{
			this.wrapMargin = this.WrapMargin;
			bool flag = this.owner.Source.Lexer != null;
			if (flag)
			{
				this.owner.Source.ParseToString(last);
			}
			int num = Math.Max(first, 0);
			int num2 = Math.Min(last, this.lines.Count - 1);
			int num3 = num;
			if (this.allowOutlining)
			{
				this.outlineList.CheckVisible(ref num);
				num3 = this.outlineList.LineToDisplayLine(num);
			}
			int num4 = 0;
			int height = this.owner.ClientRect.Height;
			int index = -1;
		
			{
				int lineHeight = this.owner.Painter.lineHeight;
				num4 = this.owner.Scrolling.WindowOriginY + ((lineHeight != 0) ? (this.owner.Height / lineHeight) : 0) + EditConsts.DefaultWrapDelta;
			}
			for (int i = num; i <= num2; i++)
			{
				if (this.WrapLine(i, ref index, num3, ref displayLine, ref this.wrapMargin, flag))
				{
					num3++;
					this.lastWrapped = i;
					this.lastDisplayIndex = num3;
					if (last == int.MaxValue)
					{
					
						{
							if (num3 >= num4)
							{
								break;
							}
						}
					}
				}
			}
			this.lastWrapIndex = this.wrapList.LineToDisplayLine(this.lastDisplayIndex);
		}
	
		private void UnWrapLines(int first, int last)
		{
			this.ClearLastLine();
			if (first == 0 && last == int.MaxValue)
			{
				this.wrapList.Clear();
			}
			else
			{
				if (this.allowOutlining)
				{
					first = this.outlineList.LineToDisplayLine(first);
					last = this.outlineList.LineToDisplayLine(last);
				}
				this.wrapList.ClearLines(first, last);
			}
		}
		protected virtual bool WrapLine(int index,  ref int page, int displayIndex, ref int displayLine, ref int margin, bool needData)
		{
			bool result;
			if (!this.allowOutlining || this.IsVisible(index))
			{
				string empty = string.Empty;
				StringItemInfo[] colorData = null;
				this.GetOutlineString(index, ref empty, ref colorData, needData, true);
				int i = 0;
				int length = empty.Length;
				if (length == 0)
				{
					displayLine++;
				}
				else
				{
					while (i < length)
					{
						int num;
						this.owner.SyntaxPaint.MeasureLine(empty, colorData, i, -1, margin, out num, true);
						if (i + num < length)
						{
							for (int j = num; j > 0; j--)
							{
								if (this.IsDelimiter(empty, i + j - 1))
								{
									num = j;
									break;
								}
							}
						}
						if (num <= 0)
						{
							num = 1;
						}
						i += num;
						if (i < length)
						{
							this.wrapList.AddItem(displayIndex, i);
						}
						displayLine++;
					}
				}
				result = true;
			}
			else
			{
				result = false;
			}
			return result;
		}
		public virtual bool UpdateWordWrap()
		{
			return this.UpdateWordWrap(0, int.MaxValue);
		}
		public virtual bool UpdateWordWrap(int first, int last)
		{
			bool flag;
			if (this.wordWrap)
			{
				int count = this.wrapList.Count;
				int displayLine = (first > 0) ? (this.PointToDisplayPoint(int.MaxValue, first - 1).Y + 1) : 0;
				this.UnWrapLines(first, last);
				this.WrapLines(first, last, displayLine);
				flag = (first != last || this.wrapList.Count != count);
			}
			else
			{
				flag = (this.wrapList.Count != 0);
				this.UnWrapLines(0, int.MaxValue);
			}
			if (flag)
			{
				last = int.MaxValue;
			}
			this.Notify(NotifyState.WordWrap, first, last, flag);
			return flag;
		}
		public virtual int GetWrapMargin()
		{
			return this.wrapMargin;
		}
	
		public virtual bool Find(string s, SearchOptions options, Regex expression, ref Point position, out int len, out Match match)
		{
			return TextStrings.Find(this, this.lines.DelimTable, s, options, expression, ref position, out len, out match, this.LineTerminator);
		}
		protected virtual void OnDelimitersChanged()
		{
		}
		
		public virtual bool IsDelimiter(string s, int pos)
		{
			return this.lines.IsDelimiter(s, pos);
		}
		public virtual bool IsWhitespace(string s, int pos)
		{
			return this.lines.IsWhitespace(s, pos);
		}
	
		public virtual bool GetWord(string s, int pos, out int left, out int right)
		{
			return this.lines.GetWord(s, pos, out left, out right);
		}
	
		public virtual string GetTextAt(int pos, int line)
		{
			string text = this[line];
			int num;
			int num2;
			string result;
			if (this.GetWord(text, pos, out num, out num2))
			{
				result = text.Substring(num, num2 - num + 1);
			}
			else
			{
				result = string.Empty;
			}
			return result;
		}
	
		private int GetOutlineLevel(Point point)
		{
			OutlineRange outlineRange = this.GetOutlineRange(point);
			return (outlineRange != null) ? (outlineRange.Level + 1) : 0;
		}
		protected virtual void OnAllowOutliningChanged()
		{
			if (!this.allowOutlining)
			{
				this.UnOutline();
			}
			else
			{
				this.owner.Outlining.OutlineText();
			}
		}
		protected virtual void OnOutlineOptionsChanged()
		{
		}
		public virtual OutlineRange Outline(int first, int last, int level)
		{
			return this.Outline(new Point(0, first), new Point(int.MaxValue, last), level, EditConsts.DefaultOutlineText);
		}
		public virtual OutlineRange Outline(int first, int last)
		{
			return this.Outline(new Point(0, first), new Point(int.MaxValue, last), this.GetOutlineLevel(new Point(0, first)), EditConsts.DefaultOutlineText);
		}
		public virtual OutlineRange Outline(Point startPoint, Point endPoint, int level)
		{
			return this.Outline(startPoint, endPoint, level, EditConsts.DefaultOutlineText);
		}
		public virtual OutlineRange Outline(Point startPoint, Point endPoint)
		{
			return this.Outline(startPoint, endPoint, this.GetOutlineLevel(startPoint), EditConsts.DefaultOutlineText);
		}
		public virtual OutlineRange Outline(int first, int last, int level, string outlineText)
		{
			return this.Outline(new Point(0, first), new Point(int.MaxValue, last), level, outlineText);
		}
		public virtual OutlineRange Outline(int first, int last, string outlineText)
		{
			return this.Outline(new Point(0, first), new Point(int.MaxValue, last), this.GetOutlineLevel(new Point(0, first)), outlineText);
		}
		public virtual OutlineRange Outline(Point startPoint, Point endPoint, int level, string outlineText)
		{
			OutlineRange result;
			if (this.allowOutlining)
			{
				OutlineRange outlineRange = new Outlining.DisplayRange(this.outlineList, startPoint, endPoint, level, outlineText);
				this.outlineList.Add(outlineRange);
				result = outlineRange;
			}
			else
			{
				result = null;
			}
			return result;
		}
		public virtual OutlineRange Outline(Point startPoint, Point endPoint, string outlineText)
		{
			return this.Outline(startPoint, endPoint, this.GetOutlineLevel(startPoint), outlineText);
		}
		public virtual void UnOutline(Point position)
		{
			this.outlineList.RemoveRange(position);
		}
		public virtual void UnOutline(int index)
		{
			this.outlineList.RemoveRange(index);
		}
		public void UnOutline()
		{
			this.outlineList.Clear();
		}
		public virtual OutlineRange GetOutlineRange(Point position)
		{
			OutlineRange result;
			if (this.allowOutlining)
			{
				result = (this.outlineList.FindRange(position) as OutlineRange);
			}
			else
			{
				result = null;
			}
			return result;
		}
		public virtual OutlineRange GetOutlineRange(int index)
		{
			OutlineRange result;
			if (this.allowOutlining)
			{
				result = (this.outlineList.FindRange(index) as OutlineRange);
			}
			else
			{
				result = null;
			}
			return result;
		}
		public virtual bool IsExpanded(int index)
		{
			OutlineRange outlineRange = this.GetOutlineRange(index);
			return outlineRange != null && outlineRange.Visible;
		}
		public virtual bool IsCollapsed(int index)
		{
			OutlineRange outlineRange = this.GetOutlineRange(index);
			return outlineRange != null && outlineRange.StartPoint.Y == index && !outlineRange.Visible;
		}
		public virtual bool IsVisible(Point position)
		{
			return this.outlineList.IsVisible(position);
		}
		public virtual bool IsVisible(int index)
		{
			return this.outlineList.IsVisible(index);
		}
		public virtual void Collapse(int index)
		{
            List<Range> list = new List<Range>();
			this.GetOutlineRanges(list, index);
			this.BeginUpdate();
			try
			{
				using (IEnumerator<Range> enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						OutlineRange outlineRange = (OutlineRange)enumerator.Current;
						if (outlineRange.StartPoint.Y == index && outlineRange.Visible)
						{
							outlineRange.Visible = false;
						}
					}
				}
			}
			finally
			{
				this.EndUpdate();
			}
		}
		public virtual void Expand(int index)
		{
			List<Range> list = new List<Range>();
			this.GetOutlineRanges(list, index);
			this.BeginUpdate();
			try
			{
				using (IEnumerator<Range> enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						OutlineRange outlineRange = (OutlineRange)enumerator.Current;
						if (outlineRange.StartPoint.Y == index && !outlineRange.Visible)
						{
							outlineRange.Visible = true;
						}
					}
				}
			}
			finally
			{
				this.EndUpdate();
			}
		}
		public virtual void EnsureExpanded(int index)
		{
			if (this.allowOutlining)
			{
				List<Range> list = new List<Range>();
				this.GetOutlineRanges(list, index);
				bool flag = false;
				using (IEnumerator<Range> enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						OutlineRange outlineRange = (OutlineRange)enumerator.Current;
						if (!outlineRange.Visible)
						{
							flag = true;
							break;
						}
					}
				}
				if (flag)
				{
					this.BeginUpdate();
					try
					{
						using (IEnumerator<Range> enumerator = list.GetEnumerator())
						{
							while (enumerator.MoveNext())
							{
								OutlineRange outlineRange = (OutlineRange)enumerator.Current;
								if (!this.CanExpand(outlineRange.StartPoint.Y))
								{
									break;
								}
								outlineRange.Visible = true;
							}
						}
					}
					finally
					{
						this.EndUpdate();
					}
				}
			}
		}
		public virtual void EnsureExpanded(Point position)
		{
			if (this.allowOutlining)
			{
				List<Range> list = new List<Range>();
				this.GetOutlineRanges(list, position);
				bool flag = false;
				using (IEnumerator<Range> enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						OutlineRange outlineRange = (OutlineRange)enumerator.Current;
						if (!outlineRange.Visible && !outlineRange.StartPoint.Equals(position))
						{
							flag = true;
							break;
						}
					}
				}
				if (flag)
				{
					this.BeginUpdate();
					try
					{
						using (IEnumerator<Range> enumerator = list.GetEnumerator())
						{
							while (enumerator.MoveNext())
							{
								OutlineRange outlineRange = (OutlineRange)enumerator.Current;
								if (!outlineRange.Visible && !outlineRange.StartPoint.Equals(position))
								{
									if (!this.CanExpand(outlineRange.StartPoint.Y))
									{
										break;
									}
									outlineRange.Visible = true;
								}
							}
						}
					}
					finally
					{
						this.EndUpdate();
					}
				}
			}
		}
		public virtual void FullExpand()
		{
			this.FullExpand(this.outlineList.GetRanges());
		}
		public virtual void FullExpand(List<Range> ranges)
		{
			if (ranges.Count > 0)
			{
				this.BeginUpdate();
				try
				{
					using (IEnumerator<Range> enumerator = ranges.GetEnumerator())
					{
						while (enumerator.MoveNext())
						{
							OutlineRange outlineRange = (OutlineRange)enumerator.Current;
							outlineRange.Visible = true;
						}
					}
				}
				finally
				{
					this.EndUpdate();
				}
			}
		}
		public virtual void FullCollapse()
		{
			this.FullCollapse(this.outlineList.GetRanges());
		}
		public virtual void FullCollapse(List<Range> ranges)
		{
			this.BeginUpdate();
			try
			{
				using (IEnumerator<Range> enumerator = ranges.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						OutlineRange outlineRange = (OutlineRange)enumerator.Current;
						outlineRange.Visible = false;
					}
				}
			}
			finally
			{
				this.EndUpdate();
			}
		}
		public virtual void ToggleOutlining()
		{
			this.ToggleOutlining(this.outlineList.GetRanges(), this.GetOutlineRange(this.owner.Position));
		}
		public virtual void ToggleOutlining(List<Range> ranges, OutlineRange range)
		{
			if (ranges.Count != 0)
			{
				if (range == null)
				{
					range = (OutlineRange)ranges[0];
				}
				if (range.Visible)
				{
					this.FullCollapse(ranges);
				}
				else
				{
					this.FullExpand(ranges);
				}
			}
		}
		public virtual void CollapseToDefinitions()
		{
			if (this.owner.Source.NeedOutlineText())
			{
				SyntaxParser syntaxParser = this.owner.Lexer as SyntaxParser;
				this.BeginUpdate();
				try
				{
					using (List<Range>.Enumerator enumerator = this.outlineList.GetEnumerator())
					{
						while (enumerator.MoveNext())
						{
							OutlineRange outlineRange = (OutlineRange)enumerator.Current;
							SyntaxNode nodeAt = syntaxParser.GetNodeAt(outlineRange.StartPoint);
							outlineRange.Visible = (nodeAt != null && syntaxParser.IsDeclaration(nodeAt));
						}
					}
				}
				finally
				{
					this.EndUpdate();
				}
			}
		}
		public virtual string GetOutlineHint(OutlineRange range)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int num = Math.Min(this.lines.Count - 1, range.EndPoint.Y);
			for (int i = range.StartPoint.Y; i <= num; i++)
			{
				string text = this.lines[i];
				if (i == range.EndPoint.Y)
				{
					text = text.Substring(0, Math.Min(text.Length, range.EndPoint.X));
				}
				if (i >= EditConsts.MaxHintWindowCount || i == num)
				{
					stringBuilder.AppendFormat("{0}", text);
					break;
				}
				stringBuilder.AppendFormat("{0}{1}", text, "\r\n");
			}
			return stringBuilder.ToString();
		}
		public virtual int GetOutlineRanges(IList<Range> ranges, int index)
		{
			if (this.allowOutlining)
			{
				this.outlineList.GetRanges(ranges, index);
			}
			else
			{
				ranges.Clear();
			}
			return ranges.Count;
		}
		public virtual int GetOutlineRanges(IList<Range> ranges, Point position)
		{
			if (this.allowOutlining)
			{
				this.outlineList.GetRanges(ranges, position);
			}
			else
			{
				ranges.Clear();
			}
			return ranges.Count;
		}
		public virtual int GetOutlineRanges(IList<Range> ranges, Point startPoint, Point endPoint)
		{
			if (this.allowOutlining)
			{
				this.outlineList.GetRanges(ranges, startPoint, endPoint);
			}
			else
			{
				ranges.Clear();
			}
			return ranges.Count;
		}
		public virtual int GetOutlineRanges(List<Range> ranges)
		{
			if (this.allowOutlining)
			{
				this.outlineList.GetRanges(ranges);
			}
			else
			{
				ranges.Clear();
			}
			return ranges.Count;
		}
		public virtual void SetOutlineRanges(List<Range> ranges)
		{
			this.SetOutlineRanges(ranges, false);
		}
		public virtual bool CanExpand(int line)
		{
			bool result = true;
			if (this.Expanding != null)
			{
				OutlineEventArgs outlineEventArgs = new OutlineEventArgs(line);
				this.Expanding(this.owner, outlineEventArgs);
				result = outlineEventArgs.CanExpand;
			}
			return result;
		}
		public virtual bool CanCollapse(int line)
		{
			bool result = true;
			if (this.Collapsing != null)
			{
				OutlineEventArgs outlineEventArgs = new OutlineEventArgs(line);
				this.Collapsing(this.owner, outlineEventArgs);
				result = outlineEventArgs.CanCollapse;
			}
			return result;
		}
		public virtual void SetOutlineRanges(List<Range> ranges, bool preserveVisible)
		{
			this.BeginUpdate();
			try
			{
				List<Range> list = new List<Range>();
				using (IEnumerator<Range> enumerator = ranges.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						OutlineRange outlineRange = (OutlineRange)enumerator.Current;
						bool flag = outlineRange.Visible;
						if (preserveVisible)
						{
							if (flag)
							{
								flag = (this.outlineList.FindCollapsedRange(outlineRange.StartPoint) == null);
							}
							else
							{
								OutlineRange outlineRange2 = this.outlineList.FindExactRange(outlineRange.StartPoint) as OutlineRange;
								flag = (outlineRange2 != null && outlineRange2.Visible);
							}
						}
						list.Add(new Outlining.DisplayRange(this.outlineList, outlineRange.StartPoint, outlineRange.EndPoint, outlineRange.Level, outlineRange.DisplayText, flag));
					}
				}
				this.outlineList.Clear();
				using (IEnumerator<Range> enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						OutlineRange outlineRange = (OutlineRange)enumerator.Current;
						this.outlineList.Add(outlineRange);
					}
				}
			}
			finally
			{
				this.EndUpdate();
			}
		}
		
		protected void Notify(NotifyState state, int first, int last, bool update)
		{
			this.owner.Notification(this, new NotifyEventArgs(state, first, last, update));
		}
		public virtual int BeginUpdate()
		{
			this.outlineList.BeginUpdate();
			this.updateCount++;
			return this.updateCount;
		}
		public virtual int EndUpdate()
		{
			this.outlineList.EndUpdate();
			this.updateCount--;
			return this.updateCount;
		}
		public virtual int DisableUpdate()
		{
			this.updateCount++;
			return this.updateCount;
		}
		public virtual int EnableUpdate()
		{
			this.updateCount--;
			return this.updateCount;
		}
		public virtual void Update()
		{
			if (this.updateCount == 0)
			{
				this.outlineList.Update();
			}
		}
		public void Notify(NotifyState state, int first, int last)
		{
			this.Notify(state, first, last, true);
		}
	}
}
